package com.project.springboot.service.cup.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gitee.yongzhuzl.commonutil.util.bean.BeanUtil;
import com.gitee.yongzhuzl.commonutil.util.random.RandomUtil;
import com.project.springboot.vo.CupVo;
import com.project.springboot.entity.Cup;
import com.project.springboot.entity.Student;
import com.project.springboot.mapper.CupMapper;
import com.project.springboot.service.StudentService;
import com.project.springboot.service.cup.CupService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * description: 杯子服务接口实现类
 * @author 朱正磊
 * @date 2023-09-19 18:59:50
 */
@Slf4j
@Service("cupService")
@Transactional
public class CupServiceImpl extends ServiceImpl<CupMapper, Cup> implements CupService {

    @Resource
    private StudentService studentService;

    @Override
    public void addCup(Cup cup) {
        try {
            this.doThing();
        } catch (Exception e) {
            log.error("异常信息：", e);
        }

        String id = RandomUtil.getUuidNoLine();
        cup.setId(id);
        cup.setCreateTime(new Date());
        this.save(cup);

        Cup newCup = this.getById(id);
        log.info("新增加的杯子 = " + newCup);
    }

    public void doThing() {
        Student student = new Student();
        student.setId((int) Math.ceil(Math.random() * 10));
        student.setName("刘德华");
        student.setSex(1);
        student.setAge(22);
        student.setAddress("香港");
        student.setHobby("拍戏");
        student.setBirthday(new Date());
        studentService.save(student);
        int i = 1 / 0;
    }

    @Override
    public List<CupVo> listCup() {
        List<Cup> list = this.list();
        List<CupVo> voList = list.stream().map(cup -> {
            CupVo vo = new CupVo();
            BeanUtil.copyProperties(cup, vo);
            return vo;
        }).collect(Collectors.toList());
        log.info("size = {}", voList.size());
        return voList;
    }

    /**
     * 会成功插入2条杯子数据和1条学生数据，因为在try代码块中，抛出异常之前的代码是会被正常执行的，抛出异常之后的代码不会被执行到
     * 因为在本Service里面的方法提取跟不提取其实没有区别，this.insertStudent();方法调用和直接写代码逻辑作用没有差别！！！
     * description: 测试Transaction rolled back because it has been marked as rollback-only
     * @author 朱正磊
     * @date 2024-05-22 15:33:11
     */
    @Override
    public void testTransactionalRollback1() {
        // 插入一条杯子数据
        this.insertCup();
        try {
            // 插入一条学生数据
            this.insertStudent();
            // 插入一条学生数据
            this.insertStudent();
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        // 插入一条杯子数据
        this.insertCup();
    }

    /**
     * 不会插入任何的杯子数据和学生数据，会抛出
     * org.springframework.transaction.UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only
     * 因为try代码块中调用了其他Service方法，而且抛出异常的代码是在其他Service方法里，同时满足这两个条件就会触发该异常
     * description: 测试Transaction rolled back because it has been marked as rollback-only
     * @author 朱正磊
     * @date 2024-05-22 15:33:11
     */
    @Override
    public void testTransactionalRollback2() {
        // 插入一条杯子数据
        this.insertCup();
        try {
            // 插入一条学生数据
            studentService.addStudent();
        } catch (Exception e) {
            log.error(e.getMessage());
            // 手动显式回滚
            // TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        // 插入一条杯子数据
        this.insertCup();
        // throw new RuntimeException("发生异常啦");
    }

    /**
     * 会成功插入2条杯子数据和1条学生数据，因为在try代码块中，抛出异常之前的代码是会被正常执行的，抛出异常之后的代码不会被执行到
     * 虽然本Service里面调用了其他Service的方法，但是是在本Service里面抛出的异常，不是在其他Service里面抛出的异常
     * description: 测试Transaction rolled back because it has been marked as rollback-only
     * @author 朱正磊
     * @date 2024-05-22 15:33:11
     */
    @Override
    public void testTransactionalRollback3() {
        // 插入一条杯子数据
        this.insertCup();
        try {
            // 插入一条学生数据
            Student student1 = new Student();
            student1.setName("王杰1");
            student1.setSex(1);
            student1.setAge(59);
            student1.setAddress("香港新界");
            student1.setHobby("唱歌");
            student1.setBirthday(new Date());
            studentService.save(student1);

            int i = 100 / 0;

            // 插入一条学生数据
            Student student2 = new Student();
            student2.setName("王杰2");
            student2.setSex(1);
            student2.setAge(59);
            student2.setAddress("香港新界");
            student2.setHobby("唱歌");
            student2.setBirthday(new Date());
            studentService.save(student2);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        // 插入一条杯子数据
        this.insertCup();
    }

    /**
     * description: 插入一条杯子数据
     * @author 朱正磊
     * @date 2024-05-22 15:38:56
     */
    private void insertCup() {
        Cup cup = new Cup();
        cup.setId(RandomUtil.getUuidNoLine());
        cup.setColor("red");
        cup.setWeight(1000);
        cup.setUnit("g");
        cup.setPrice(new BigDecimal("120"));
        cup.setCreateTime(new Date());
        this.save(cup);
    }

    /**
     * description: 插入一条学生数据
     * @author 朱正磊
     * @date 2024-05-22 15:38:56
     */
    private void insertStudent() {
        Student student = new Student();
        student.setName("郭富城");
        student.setSex(1);
        student.setAge(55);
        student.setAddress("香港旺角");
        student.setHobby("跳舞");
        student.setBirthday(new Date());
        studentService.save(student);
        throw new RuntimeException("发生未知异常！");
    }

    /**
     * 不涉及任何的增删查改，就只是ServiceA的方法调用ServiceB的方法，发现照样会抛出Transaction silently rolled back because it has been marked as rollback-only
     * 说明了只要满足ServiceA的方法调用ServiceB的方法，并且ServiceB的方法抛出了异常，ServiceA的方法对ServiceB的方法进行了try catch，但是catch里面没有对异常进行处理比如继续抛出或者手动回滚，
     * 就会出现Transaction silently rolled back because it has been marked as rollback-only
     * description: 测试Transaction rolled back because it has been marked as rollback-only
     * @author 朱正磊
     * @date 2025-06-21 13:05:44
     */
    @Override
    public void testTransactionalRollback4() {

        System.out.println("你还好吗");

        try {
            // 根据姓名查询学生
            Student student = studentService.getStudentByName("王杰");
            System.out.println("student = " + student);
        } catch (Exception e) {
            log.error(e.getMessage());
        }

        System.out.println("我很好");

    }

    /**
     * description: 查询所有的杯子
     * @author 朱正磊
     * @date 2025-06-21 13:24:23
     * @return 返回杯子集合
     */
    private List<Cup> selectCupList() {
        return this.list();
    }

    /**
     * description: 根据主键查询唯一杯子
     * @author 朱正磊
     * @date 2025-06-21 13:24:23
     * @return 返回唯一杯子
     */
    private Cup selectOneCup(String id) {
        return this.getById(id);
    }

    /**
     * 说明：使用Spring事务传播机制PROPAGATION_NESTED
     * 看现象是不是：nested 的子异常抛出 如果被catch 外部插入成功
     * description: 测试Transaction rolled back because it has been marked as rollback-only
     * @author 朱正磊
     * @date 2025-10-22 09:19:05
     */
    @Override
    public void testTransactionalRollback5() {
        this.insertCup();

        try {
            studentService.saveStudent();
        } catch (Exception e) {
            log.error(e.getMessage());
        }

        this.insertCup();
    }

    /**
     * 说明：使用Spring事务传播机制PROPAGATION_NESTED
     * 看现象是不是：nested 的子异常抛出 如果不被catch 外部插入失败
     * description: 测试Transaction rolled back because it has been marked as rollback-only
     * @author 朱正磊
     * @date 2025-10-22 09:19:05
     */
    @Override
    public void testTransactionalRollback6() {
        this.insertCup();

        studentService.saveStudent();

        this.insertCup();
    }

    /**
     * 说明：使用Spring事务传播机制PROPAGATION_NESTED
     * 看现象是不是：nested外面异常抛出 nest内部插入成功 nest也会跟着回滚
     * description: 测试Transaction rolled back because it has been marked as rollback-only
     * @author 朱正磊
     * @date 2025-10-22 09:19:05
     */
    @Override
    public void testTransactionalRollback7() {
        this.insertCup();

        studentService.createStudent();

        this.insertCup();

        int i = 10 / 0;
    }

}
